# Copyright (c) 2007 Kimmo Parviainen <kimvais@gmail.com>
# See the LICENSE file for details

import random,hexposition
def create_hills(m,amount):
	for i in range(amount):
		x = random.randint(int(m.x*.1),int(m.x*.9))
		y = random.randint(int(m.y*.1),int(m.y*.9))
		z = 2*random.randint(1,2)
		m.data[x][y]['z']+=z
		if z > 2:
			for nx,ny in hex.neighbours(x,y):
				if nx >= m.x or ny >=m.y or nx < 0 or ny < 0:
					continue
				m.data[nx][ny]['z']+=2

def generate_terrain(m):
	ax = 1
	ay = 4
	bx = m.x-2
	by = m.y-3
	cx = bx/2
	cy = by/2
	print "%d,%d - %d,%d" % (ax,ay,bx,by)
	
	delta=random.randint(0,min(16,(bx-ax)/4))
	# Deep edges
	for x in range(m.x):
		m.setz((x,0),-delta)
		m.setz((x,1),-delta)
		m.setz((x,m.y-1),-delta)
		m.setz((x,m.y-2),-delta)
	for y in range(m.y):
		m.setz((0,y),-delta)
		m.setz((m.x-1,y),-delta)

	m.setz((cx,cy),delta*2)
	fractalize(m,(ax,ay),(cx,cy))
	fractalize(m,(cx,ay),(bx,cy))
	fractalize(m,(ax,cy),(cx,by))
	fractalize(m,(cx,cy),(bx,by))

def generate_mountain_ranges(m,amount):
	for i in range(amount):
		generate_range(m,8)

def generate_canyons(m,amount):
	for i in range(amount):
		generate_range(m,-8)

def generate_range(m,maxheight):
	minheight=maxheight/2
	rx = random.randint(1,m.x-1)
	ry = random.randint(4,m.y-3)
	pos = hexposition.position((rx,ry),random.randint(0,5))
	# print "starting new mountain range at: %d,%d" % (rx,ry)
	nei = []
	mts = []
	while 1:
		switch = random.randint(1,100)
		if switch < 60:
			#print "turning to: %d" % (switch%2-1)
			pos.turn(switch%2-1)
		elif switch < 97:
			if maxheight > 0:
				d = random.randint(minheight,maxheight)
			else:
				d = random.randint(maxheight,minheight)
			#print "rising: %d,%d" % mountain.where()
			pos.walk(2)
			if pos.where in mts:
				continue
			m.rise(pos.where(),d)
			nei += m.neighbours(pos.where())
			mts += pos.where()
			if pos.where() in nei:
				nei.remove(pos.where())
		else:
			#print "ending range"
			break
	for n in nei:
		m.setz(n,m.getavgz(m.neighbours(n))+minheight/2)

def rnd(n):
	return random.randint(-n,n)

def fractalize(m,topleft,botright):
	ax,ay = topleft
	bx,by = botright
	topright = (bx,ay)
	botleft = (ax,by)
	wt = random.randint(0,max(min(16,(bx-ax)/3),5))

	if bx-ax <= 1:
		m.setz((ax,ay+2),m.getavgz(topleft,botleft)+rnd(wt))
		m.setz((bx,ay+2),m.getavgz(topright,botright)+rnd(wt))
		m.setz((ax,ay+1),m.getavgz(topright,topleft)+rnd(wt))
		m.setz((ax,by-1),m.getavgz(botright,botleft)+rnd(wt))
		
	else:
		cx = (ax+bx)/2
		cy = (ay+by)/2

		topmiddle = (cx,ay)
		leftmiddle = (ax,cy)
		center = (cx,cy)
		rightmiddle = (bx,cy)
		botmiddle = (cx,by)

		m.setz(center,m.getavgz(topleft,topright,botright,botleft)+rnd(wt))
		m.setz(topmiddle,m.getavgz(topleft,topright,center)+rnd(wt))
		m.setz(leftmiddle,m.getavgz(topleft,botleft,center)+rnd(wt))
		m.setz(rightmiddle,m.getavgz(center,topright,botright)+rnd(wt))
		m.setz(botmiddle,m.getavgz(center,botright,botleft)+rnd(wt))

		fractalize(m,topleft,center)
		fractalize(m,topmiddle,rightmiddle)
		fractalize(m,leftmiddle,botmiddle)
		fractalize(m,center,botright)

def create_river(m,coords):
	if m.getstreams(coords) > 0:
		return
	path = [coords]
	turn = 0
	turndir = 1
	slopefrom = m.getmaxz(m.neighbours(coords))[1]
	down = (m.neighbours(coords).index(slopefrom)+3)%6
	river = hexposition.position(coords,down)
	height = m.getz(coords)
	while 1:
		river.walk()
		coords = river.where()
		#print "Walked to ",coords
		if coords in path:
			print "Fuxxored!"
			break
		if m.getz(coords) < 0 or m.getstreams(coords) > 0:
			path.append(coords)
			print "River met sea or other river!"
			break
		nei = m.neighbours(coords)
		if m.getminz(nei)[0] > height:
			print "No way out!"
			break
		if m.getz(coords) <= height:
			path.append(coords)
			height = m.getz(coords)
			print coords,height
			turndir *= -1
			river.turn(turndir,1)
			turn = 0
		else:
			river.walk(1,True)
			turn +=1
			turndir *= -1
			#print "Turning %s (%d)" % (turndir,turn)
			river.turn(turndir,turn)		
	for coords in path:
		m.addstream(coords)
	m.rivers.append(path)


def generate_rivers(m,amount):
	for x in range(0,m.x):
		for y in range(0,m.y):
			if random.randint(0,128) < m.getz((x,y)):
				create_river(m,(x,y))
"""
	for i in range(amount):
		x = random.randint(1,m.x-1)
		y = random.randint(2,m.y-2)
		create_river(m,(x,y))
"""

def erode(m):
	for i in range(3):
		for y in range(1+i,m.y-1,3):
			for x in range(0,m.x-1):
				neighbours = m.neighbours((x,y))
				if len(neighbours)>2:
					m.setz((x,y),m.getavgz(neighbours))
